﻿using Styx;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Styx.WoWInternals;
using System.Collections;


#region [Method] Class Reduduncy
using L = SinisterD.Core.Utilities.Log;
using SB = SinisterD.Core.Helpers.Spell_Book;
#endregion


namespace SinisterD.Core
{
    static class Unit
    {
        private static LocalPlayer Me { get { return StyxWoW.Me; } }
        private static WoWUnit currentTarget { get { return StyxWoW.Me.CurrentTarget; } }

        #region [Method] - Active Enemies
        public static IEnumerable<WoWUnit> activeEnemies(WoWPoint fromLocation, double Range)
        {
            var Hostile = enemyCount;
            return Hostile != null ? Hostile.Where(x => x.Location.DistanceSqr(fromLocation) < Range * Range) : null;
        }

        private static List<WoWUnit> enemyCount { get; set; }

        public static void enemyAnnex(double Range)
        {
            enemyCount.Clear();
            foreach (var u in surroundingEnemies())
            {
                if (u == null || !u.IsValid)
                    continue;
                if (!u.IsAlive || u.DistanceSqr > Range * Range)
                    continue;
                if (!u.Attackable || !u.CanSelect)
                    continue;
                if (u.IsFriendly)
                    continue;
                if (u.IsNonCombatPet && u.IsCritter)
                    continue;
                enemyCount.Add(u);
            }
        }

        private static IEnumerable<WoWUnit> surroundingEnemies() { return ObjectManager.GetObjectsOfTypeFast<WoWUnit>(); }

        static Unit() { enemyCount = new List<WoWUnit>(); }
        #endregion

        #region [Method] - Aura Detection
        //Method for if aura exists
        public static bool auraExists(this WoWUnit Unit, int auraID, bool isMyAura = false)
        {
            try
            {
                if (Unit == null || !Unit.IsValid)
                    return false;
                WoWAura Aura = isMyAura ? Unit.GetAllAuras().FirstOrDefault(A => A.SpellId == auraID && A.CreatorGuid == Me.Guid) : Unit.GetAllAuras().FirstOrDefault(A => A.SpellId == auraID);
                return Aura != null;
            }
            catch (Exception xException)
            {
                L.diagnosticLog("Exception in auraExists(): ", xException);
                return false;
            }
        }

        //Method for if aura stacks
        public static uint auraStacks(this WoWUnit Unit, int auraID, bool isMyAura = false)
        {
            try
            {
                if (Unit == null || !Unit.IsValid)
                    return 0;
                WoWAura Aura = isMyAura ? Unit.GetAllAuras().FirstOrDefault(A => A.SpellId == auraID && A.CreatorGuid == Me.Guid) : Unit.GetAllAuras().FirstOrDefault(A => A.SpellId == auraID);
                return Aura != null ? Aura.StackCount : 0;
            }
            catch (Exception xException)
            {
                L.diagnosticLog("Exception in auraStacks(): ", xException);
                return 0;
            }
        }
        //Methof for time left on aura
        public static double auraTimeLeft(this WoWUnit Unit, int auraID, bool isMyAura = false)
        {
            try
            {
                if (Unit == null || !Unit.IsValid)
                    return 0;
                WoWAura Aura = isMyAura ? Unit.GetAllAuras().FirstOrDefault(A => A.SpellId == auraID && A.CreatorGuid == Me.Guid) : Unit.GetAllAuras().FirstOrDefault(A => A.SpellId == auraID);
                return Aura != null ? Aura.TimeLeft.TotalMilliseconds : 0;
            }
            catch (Exception xException)
            {
                L.diagnosticLog("Exception in auraTimeLeft(): ", xException);
                return 9999;
            }
        }

        #endregion

        #region [Method] - Cache
        public static double SnD;
        public static double RevStrike;
        public static uint Energy;
        public static int CP;
        public static uint AntiStacks;
        public static bool Vanish;
        public static bool Stealth;
        public static bool BLup;
        public static double BLtime;

        public static void Cache()
        {
            SnD = auraTimeLeft(Me, SB.auraSliceAndDice);
            RevStrike = auraTimeLeft(currentTarget, SB.auraRevealingStrike, true);
            CP = Me.ComboPoints;
            Energy = Me.CurrentEnergy;
            AntiStacks = auraStacks(Me, SB.auraAnticipation);
            BLup = auraExists(Me, SB.auraHeroism) || auraExists(Me, SB.auraAncientHysteria) || auraExists(Me, SB.auraNetherwinds) || auraExists(Me, SB.auraBloodlust) || auraExists(Me, SB.auraTimewarp);
        }
        #endregion

        #region [Method] - Unit Evaluation
        public static bool isUnitValid(this WoWUnit Unit, double Range)
        {
            return Unit != null && Unit.IsValid && Unit.IsAlive && Unit.Attackable && currentTarget.Distance - (currentTarget.CombatReach) - 1 <= Range ;
        }
        #endregion
    }
}